package partner_admin_users

import (
	"fmt"
	"gitee.com/theegg/go-brick/app/model"
	"gitee.com/theegg/go-brick/app/model/admin/admin_roles"
	"gitee.com/theegg/go-brick/app/model/partner/partner_admin/partner_admin_menus"
	"gitee.com/theegg/go-brick/app/model/partner/partner_admin/partner_admin_permissions"
	"gitee.com/theegg/go-brick/app/model/partner/partner_admin/partner_admin_role_users"
	"gitee.com/theegg/go-brick/app/model/partner/partner_admin/partner_admin_roles"
	"gitee.com/theegg/go-brick/app/model/partner/partner_admin/partner_admin_user_permissions"
	"gitee.com/theegg/go-brick/app/model/system/system_images"
	"gitee.com/theegg/go-brick/app/service/app"
	"gitee.com/theegg/go-brick/app/service/help/cbcrypt"
	"gitee.com/theegg/go-brick/app/service/help/cjwt"
	"gitee.com/theegg/go-brick/app/service/help/cmap"
	"sort"
	"time"
)

// @title 修改　登陆　密码参数
type AdminUserLoginPasswordParams struct {
	Id                 int64  `form:"id" json:"id"  binding:"required" label:"用户ID"`
	Action             string `form:"action" json:"action"  binding:"required" label:"动作"`
	Password           string `form:"password" json:"password"  binding:"required,min=6,max=24" label:"登陆密码"`
	ConfirmPassword    string `form:"confirm_password" json:"confirm_password"  binding:"required,min=6,max=24" label:"确认登陆密码"`
	CurrentSecPassword string `form:"current_sec_password" json:"current_sec_password"  binding:"" label:"登陆用户安全密码"`
}

// @title 修改　安全　密码参数
type AdminUserSecPasswordParams struct {
	Id                 int64  `form:"id" json:"id"  binding:"required" label:"用户ID"`
	Action             string `form:"action" json:"action"  binding:"required" label:"动作"`
	SecPassword        string `form:"sec_password" json:"sec_password"  binding:"required,min=6,max=24" label:"安全密码"`
	ConfirmSecPassword string `form:"confirm_sec_password" json:"confirm_sec_password"  binding:"required,min=6,max=24" label:"确认安全密码"`
	CurrentSecPassword string `form:"current_sec_password" json:"current_sec_password"  binding:"" label:"登陆用户安全密码"`
}

// @title 基础信息
type AdminUserBaseInfoParams struct {
	Id          int64  `form:"id" binding:"required" label:"用户ID"`
	Action      string `form:"action" binding:"required" label:"动作"`
	Username    string `form:"username" binding:"required,customMin=6,customMax=24" label:"用户昵称"`
	ImageAvatar string `form:"image_avatar"  binding:"omitempty,min=12,max=128" label:"用户头像"`
}

// @title 添加用户参数
type AdminUsersAddParams struct {
	Ip          string
	RoleId      int64  `form:"role_id" binding:"required" label:"角色"`
	Email       string `form:"email" binding:"required,email,min=8,max=32" label:"Email"`
	Username    string `form:"username" binding:"required,customMin=6,customMax=18" label:"用户名"`
	Password    string `form:"password" binding:"required,min=6,max=24" label:"登陆密码"`
	SecPassword string `form:"sec_password" binding:"required,min=6,max=24" label:"安全密码"`
	ImageAvatar string `form:"image_avatar"  binding:"omitempty,min=12,max=128" label:"用户头像"`
}

// @title 查询参数
type AdminUsersQueryParams struct {
	PageSize  string `form:"page_size" binding:"required,gte=0,lte=100" label:"每页数量"`
	PageIndex string `form:"page_index" binding:"required,gte=0,lte=99999" label:"当前页数"`
	Username  string `form:"username" binding:"omitempty,min=6,max=18" label:"用户名"`
	Email     string `form:"email" binding:"omitempty,email" label:"邮箱"`
}

// @title 查询参数
type TableJoinAdminUsersAdminRoleUser struct {
	PartnerAdminUsers `xorm:"extends"`
	Name              string
}

// 定义当前登陆用户
var (
	CurrentAdminUser PartnerAdminUsers
)

// 是否存在用户
func HasUserFromEmail(email string) (bool, error) {
	user := new(PartnerAdminUsers)

	has, err := app.Db().Where("email = ?", email).Get(user)

	if err != nil {
		return false, err
	} else {
		if !has {
			return false, app.NewError("对不起, 不存在的用户!")
		}
	}

	return true, nil
}

// 登陆用户
// params email 用户名
// params password 加密过的字符串
// return  user, bool
func UserLogin(email string, password string, ip string) (*PartnerAdminUsers, error) {

	user := new(PartnerAdminUsers)

	has, err := app.Db().Where("email = ?", email).Get(user)

	if err != nil {
		return user, err
	}

	if !has {
		return user, app.NewError("对不起, 用户名或者密码不存在")
	}

	// 检测密码
	if !cbcrypt.CheckEncode(user.Password, password) {
		return user, app.NewError("对不起, 用户名或者密码不存在")
	}

	// 更新数据
	updateUser := new(PartnerAdminUsers)
	updateUser.LastLoginTime = time.Now().Unix()
	updateUser.LastLoginIp = ip
	affected, errUpdate := app.Db().ID(user.Id).Update(updateUser)

	if errUpdate != nil {
		return user, errUpdate
	}

	if affected != 1 {
		return user, app.NewError("对不起, 更新用户数据失败")
	}

	return user, nil
}

// 根据用户生成token
func (pau PartnerAdminUsers) GenToken() (string, error) {
	jwtOp := cjwt.NewTokenContainer("partner")
	token, err := jwtOp.GenToken(EncodeUserId(pau.Id))
	if err != nil {
		return "", err
	}

	_, errSet := SetTokenCacheById(pau.Id, token, jwtOp.ExpireTime())
	if errSet != nil {
		return "", errSet
	}

	return token, err
}

// @title CheckToken
// @description 检测用户传来的token是否已经过期,或者被踢下线
func (pau PartnerAdminUsers) CheckToken(token string) (bool, error) {
	tokenCache, err := GetTokenFromCacheById(pau.Id)
	if err != nil {
		return false, err
	}

	if tokenCache == "" {
		return false, app.NewError("对不起, Token不存在!")
	}

	if tokenCache != token {
		return false, app.NewError("对不起, Token已过期!")
	}

	return true, err
}

// 分页获取所有数据
// 角色 为当前登陆 直接下级角色
// @param params map 参数
// @param pageSize int 每页数据量
// @return mix
func GetDataList(params map[string]interface{}, currentRole partner_admin_roles.PartnerAdminRoles) (map[string]interface{}, error) {
	returnData := make(map[string]interface{})

	queryParams, err := model.BuildAdminQueryParam(params)
	if err != nil {
		return nil, app.NewError(err)
	}

	// 当前登陆用户的所有下级
	allChildRoleIds, errChild := currentRole.GetChildRoleIds(true)
	if errChild != nil {
		return nil, app.NewError(errChild)
	}

	// 获取 role下的所有用户
	userIds, errRoleUser := partner_admin_roles.GetMultiRoleBindUserIds(allChildRoleIds)
	if errRoleUser != nil {
		return nil, app.NewError(errRoleUser)
	}

	items := make([]TableJoinAdminUsersAdminRoleUser, 0)
	query := app.Db().Join("LEFT", "partner_admin_role_users", "partner_admin_role_users.user_id = partner_admin_users.id").
		Join("LEFT", "partner_admin_roles", "partner_admin_role_users.role_id = partner_admin_roles.id").
		Desc("partner_admin_users.id").In("partner_admin_users.id", userIds).Limit(queryParams.Limit, queryParams.Offset)

	// 用户名
	if v, ok := queryParams.Params["username"]; ok && v != "" {
		query.And("partner_admin_users.username = ?", queryParams.Params["username"])
	}

	// 邮箱
	if v, ok := queryParams.Params["email"]; ok && v != "" {
		query.And("partner_admin_users.email = ?", queryParams.Params["email"])
	}

	// 查询多条数据
	total, errQuery := query.FindAndCount(&items)
	if errQuery != nil {
		return nil, app.NewError(errQuery)
	}

	for id, item := range items {
		items[id].ImageAvatarUrl = app.GetImageStaticUrl(item.ImageAvatar)
	}

	returnData["total"] = total
	returnData["data"] = items

	return returnData, nil
}

// 根据token构建当前登陆用户
func GenCurrentUser(userId int64) (*PartnerAdminUsers, error) {
	user := new(PartnerAdminUsers)

	has, err := app.Db().ID(userId).Get(user)

	if err != nil {
		return nil, err
	}

	if !has {
		return nil, fmt.Errorf("登陆失败, 不存在的用户")
	}

	return user, err
}

// @title 获取　权限　从用户的角色
// @description 用户拥有不同的角色　不同的角色有各自分配的订单 查找出来合并
func (pau PartnerAdminUsers) GetPermissionFromRole() ([]string, error) {

	// 获取当前用户的角色
	role, err := pau.Role()
	if err != nil {
		return nil, app.NewError("获取用户角色失败-" + err.Error())
	}

	// 获取所有的菜单
	permissions, err := partner_admin_permissions.GetItemsByRoleIdFromCache(role.Id, role.IsSuperRole())
	if err != nil {
		return nil, app.NewError(err)
	}

	// 返回组装后的数据
	var returnDataData = make([]string, 0)
	for _, v := range permissions {
		returnDataData = append(returnDataData, v.Route)
	}

	return returnDataData, nil
}

// 添加 / 更新 管理用户
// 不用反射合并结构体
func (pau *PartnerAdminUsers) AddAdminUser(params AdminUsersAddParams, currentAdminUser *PartnerAdminUsers) (*PartnerAdminUsers, error) {

	var affected int64
	var err error

	// 1. 检测email 的唯一性
	if IsFieldExist("email", params.Email) {
		return nil, app.NewError("对不起, Email已经存在")
	}

	// 2. 检测username 的唯一性
	if IsFieldExist("username", params.Email) {
		return nil, app.NewError("对不起, username已经存在")
	}

	// 3. == 1 检测当前角色
	currentRole, errRole := currentAdminUser.Role()
	if errRole != nil {
		return nil, app.NewError(errRole)
	}

	// 4. == 2 检测下级角色
	childRole, errChildRole := partner_admin_roles.GetItemById(params.RoleId)
	if errChildRole != nil {
		return nil, app.NewError(errChildRole)
	}

	// 5. == 2 判断角色是否为下级
	if ok, errHas := currentRole.HasChildRole(childRole.Id); !ok || errHas != nil {
		return nil, app.NewError("对不起, 您没有分配此角色的权限")
	}

	// 6. 开启事务 插入数据
	session := app.Db().NewSession()
	defer session.Close()
	errSb := session.Begin()
	if errSb != nil {
		return nil, app.NewError(errSb)
	}

	// 插入数据
	pau.Password = cbcrypt.Make(params.Password)
	pau.SecPassword = cbcrypt.Make(params.SecPassword)
	pau.Email = params.Email
	pau.Username = params.Username

	pau.ImageAvatar = params.ImageAvatar

	pau.RegisterTime = time.Now().Unix()
	pau.RegisterIp = params.Ip
	pau.AddAdminId = CurrentAdminUser.Id

	affected, err = session.Insert(pau)

	if err != nil {
		session.Rollback()
		return nil, app.NewError(err)
	}

	if affected != 1 {
		session.Rollback()
		return nil, app.NewError("新增用户错误(0x001)")
	}

	// 添加用户到角色 ## 鉴于事务嵌套的麻烦 插入表
	adminRoleUser := new(partner_admin_role_users.PartnerAdminRoleUsers)
	adminRoleUser.UserId = pau.Id
	adminRoleUser.RoleId = params.RoleId

	affectedInsert, errBind := session.Insert(adminRoleUser)
	if errBind != nil {
		session.Rollback()
		return nil, app.NewError(errBind)
	}

	if affectedInsert != 1 {
		session.Rollback()
		return nil, app.NewError("新增角色用户关联失败")
	}

	// 图片 mark
	imageAddObj := new(system_images.SystemImages)
	imageAddObj.ItemId = pau.Id
	imageAddObj.State = 1
	affectedAdd, errAdd := session.Where("image_name = ?", params.ImageAvatar).Cols("status", "item_id").Update(imageAddObj)
	if errAdd != nil {
		session.Rollback()
		return nil, app.NewError(errAdd)
	}

	if affectedAdd != 1 {
		session.Rollback()
		return nil, app.NewError("添加图片记录数不正确")
	}

	// 提交
	errCommit := session.Commit()
	if errCommit != nil {
		return nil, app.NewError(errCommit)
	}

	// １　刷新　用户和角色　绑定缓存
	ok := partner_admin_role_users.FlushCacheByTag()

	if !ok {
		return nil, app.NewError("刷新缓存失败")
	}

	// 2　刷新　用户和下级　绑定缓存
	_, errChildrenFlush := DeleteChildrenCacheById(currentAdminUser.Id)

	if errChildrenFlush != nil {
		return nil, app.NewError(errChildrenFlush)
	}

	return pau, nil
}

//　@title 修改登陆密码
func (pau PartnerAdminUsers) ModifyLoginPassword(params AdminUserLoginPasswordParams) (bool, error) {
	updateData := PartnerAdminUsers{
		Password: cbcrypt.Make(params.Password),
	}

	affected, err := app.Db().ID(pau.Id).Cols("password").Update(updateData)
	if err != nil {
		return false, app.NewError(err)
	}

	if affected == 0 {
		return false, app.NewError("对不起, 修改登陆密码失败")
	}

	// 刷新token
	_, errDelToken := DeleteTokenCacheById(pau.Id)
	if errDelToken != nil {
		return false, errDelToken
	}

	return true, nil
}

// @title 修改安全密码
func (pau PartnerAdminUsers) ModifySecPassword(params AdminUserSecPasswordParams) (bool, error) {
	updateData := PartnerAdminUsers{
		Password: cbcrypt.Make(params.SecPassword),
	}

	affected, err := app.Db().ID(pau.Id).Cols("sec_password").Update(updateData)
	if err != nil {
		return false, app.NewError(err)
	}

	if affected == 0 {
		return false, app.NewError("对不起, 修改安全密码失败")
	}

	return true, nil
}

// @title ModifyBaseInfo
// @description 修改基础信息
func (pau PartnerAdminUsers) ModifyBaseInfo(params AdminUserBaseInfoParams) (bool, error) {
	updateData := PartnerAdminUsers{
		ImageAvatar: params.ImageAvatar,
		Username:    params.Username,
	}

	// 昵称不能重复
	if pau.Username != params.Username {
		if IsFieldExist("username", params.Username) {
			return false, app.NewError("对不起, 用户昵称已经存在")
		}
	}

	// 开启事物
	session := app.Db().NewSession()
	defer session.Close()
	errSb := session.Begin()
	if errSb != nil {
		return false, app.NewError(errSb)
	}

	if pau.ImageAvatar != params.ImageAvatar {
		// 如果原图不为空 需要变更原图状态
		if pau.ImageAvatar != "" {
			// 删除 image
			imageDelObj := new(system_images.SystemImages)
			imageDelObj.State = 0
			affectedDel, errDel := session.Where("image_name = ?", pau.ImageAvatar).Cols("status").Update(imageDelObj)

			fmt.Println(affectedDel)

			if errDel != nil {
				session.Rollback()
				return false, app.NewError(errDel)
			}

			if affectedDel != 1 {
				session.Rollback()
				return false, app.NewError("删除图片记录数不正确")
			}
		}

		// 新增 image
		imageAddObj := new(system_images.SystemImages)
		imageAddObj.ItemId = pau.Id
		imageAddObj.State = 1
		affectedAdd, errAdd := session.Where("image_name = ?", params.ImageAvatar).Cols("status", "item_id").Update(imageAddObj)
		if errAdd != nil {
			session.Rollback()
			return false, app.NewError(errAdd)
		}

		if affectedAdd != 1 {
			session.Rollback()
			return false, app.NewError("添加图片记录数不正确")
		}
	}

	affected, err := session.ID(pau.Id).Cols("username", "image_avatar").Update(updateData)
	if err != nil {
		session.Rollback()
		return false, app.NewError(err)
	}

	if affected == 0 {
		session.Rollback()
		return false, app.NewError("对不起, 修改用户信息失败")
	}

	// 刷新用户缓存
	_, errDelCache := DeleteCacheById(pau.Id)
	if errDelCache != nil {
		session.Rollback()
		return false, errDelCache
	}

	// 提交
	errCommit := session.Commit()
	if errCommit != nil {
		return false, errCommit
	}

	return true, nil
}

// @title ModifyState
// @description 修改管理员状态
func (pau PartnerAdminUsers) ModifyState() (bool, error) {
	state := 1
	if pau.State == 1 {
		state = 0
	}

	affected, err := app.Db().Table(new(PartnerAdminUsers)).ID(pau.Id).Cols("state").Update(map[string]int{"state": state})

	if err != nil {
		return false, app.NewError(err)
	}

	// 生效条数
	if affected == 0 {
		return false, app.NewError("对不起, 指定的ID更新数量不正确")
	}

	// 删除token
	if state == 0 {
		// 刷新token
		_, errDelToken := DeleteTokenCacheById(pau.Id)
		if errDelToken != nil {
			return false, errDelToken
		}
	}

	return true, nil
}

// 获取 当前用户 可以分配的角色
// 如果当前为超级管理员 需要屏蔽， 超级管理组只能后台添加
// @return map[int64]string k => v 形式 map
func (pau PartnerAdminUsers) GetUserCanAssignRoles() (map[int64]string, error) {
	role, err := pau.Role()
	if err != nil {
		return nil, err
	}

	returnRoleData := make(map[int64]string)
	roles, err := role.GetRolesByPid(role.Id)
	if err != nil {

	}

	// 加上自己
	roles[role.Id] = *role

	for rk, rv := range roles {
		// 超级管理角色 去除
		if rk == admin_roles.SupperRoleId {
			continue
		}
		returnRoleData[rk] = rv.Name
	}

	return returnRoleData, nil
}

// 获取 当前用户 可以分配的权限
// @param ignoreRolePermissions 是否忽略
func (pau PartnerAdminUsers) GetUserCanAssignPermissions(ignoreRolePermissions bool) (map[int64]string, error) {
	// 1. 获取用户拥有的权限
	permissions, err := pau.Permissions()
	if err != nil {
		return nil, err
	}

	returnData := make(map[int64]string)

	// 如果不忽略角色的权限
	if !ignoreRolePermissions {
		for k, v := range permissions {
			returnData[k] = v.Name
		}

		return returnData, nil
	}

	role, errRole := pau.Role()
	if errRole != nil {
		return nil, errRole
	}

	// 获取角色的权限
	rolePermissions, errPer := role.Permissions()
	if errPer != nil {
		return nil, errPer
	}

	for k, v := range permissions {
		if _, ok := rolePermissions[k]; ok {
			continue
		}
		returnData[k] = v.Name
	}

	return returnData, nil
}

// 获取 当前用户 允许的权限 角色被分配 + 用户被分配
// @param ignoreRolePermissions 是否忽略
func (pau PartnerAdminUsers) GetUserAllowedPermissions() (map[string]*partner_admin_permissions.PartnerAdminPermissions, error) {
	// 1. 获取 用户 分配的权限
	permissions, err := pau.Permissions()
	if err != nil {
		return nil, err
	}

	// 2. 获取角色
	role, errRole := pau.Role()
	if errRole != nil {
		return nil, errRole
	}

	// 3. 获取 角色 分配的权限
	rolePermissions, errPer := role.Permissions()
	if errPer != nil {
		return nil, errPer
	}

	returnData := make(map[string]*partner_admin_permissions.PartnerAdminPermissions)

	for _, v := range permissions {
		if _, ok := returnData[v.Route]; ok {
			continue
		}
		returnData[v.Route] = v
	}

	for _, rv := range rolePermissions {
		if _, ok := returnData[rv.Route]; ok {
			continue
		}
		returnData[rv.Route] = rv
	}

	return returnData, nil
}

// @title EditUserPermissions
// @description 编辑用户的权限
func (pau *PartnerAdminUsers) EditUserPermissions(targetUser *PartnerAdminUsers, permissionIds map[int64]int64) (bool, error) {
	// 1. 是否超级用户
	isSupper, errSupper := pau.IsSuperAdminUser()
	if errSupper != nil {
		return false, app.NewError(errSupper)
	}

	// 1. 获取当前用户 分配的　权限
	currentPermissions, errCm := partner_admin_permissions.GetAdminPermissionsByUserIdFromDb(pau.Id, isSupper)
	if errCm != nil {
		return false, errCm
	}

	// 2. 检测　ID　是否是当前 登陆用户 已经分配了提交的权限ID
	for _, id := range permissionIds {
		if _, ok := currentPermissions[id]; !ok {
			return false, app.NewError("对不起, 无效的 permission Id")
		}
	}

	// 3. 获取目标用户已经分配的权限ID
	targetPermissions, errTp := partner_admin_permissions.GetAdminPermissionsByUserIdFromDb(targetUser.Id)
	if errTp != nil {
		return false, errTp
	}

	// 4. 遍历出哪些是新增
	addPermissionIds := make([]int64, 0)
	for _, id := range permissionIds {
		if _, ok := targetPermissions[id]; !ok {
			addPermissionIds = append(addPermissionIds, id)
		}
	}

	// 5. 遍历出哪些是移除
	removePermissionIds := make([]int64, 0)
	for tId, _ := range targetPermissions {
		if ok := cmap.IsValueInt64ExistMapInt64(tId, permissionIds); !ok {
			removePermissionIds = append(removePermissionIds, tId)
		}
	}

	/* =============================  开始事务  ================================= */
	session := app.Db().NewSession()
	defer session.Close()
	errSb := session.Begin()
	if errSb != nil {
		return false, app.NewError(errSb)
	}

	// 5-1. 目标角色增加菜单
	if len(addPermissionIds) > 0 {
		userPermissions := make([]partner_admin_user_permissions.PartnerAdminUserPermissions, 0)
		for _, aV := range addPermissionIds {
			tmpStruct := partner_admin_user_permissions.PartnerAdminUserPermissions{
				UserId:       targetUser.Id,
				PermissionId: aV,
			}

			userPermissions = append(userPermissions, tmpStruct)
		}

		_, errInsert := session.Insert(&userPermissions)
		if errInsert != nil {
			session.Rollback()
			return false, errInsert
		}
	}

	// 5-2. 下级角色减少菜单
	// 获取当前角色所有的下级 直接 + 下下级
	childUserIds, errChildRole := targetUser.ChildIds()
	if errChildRole != nil {
		session.Rollback()
		return false, errChildRole
	}

	childUserIds = append(childUserIds, targetUser.Id)

	if len(removePermissionIds) > 0 {
		aprStruct := new(partner_admin_user_permissions.PartnerAdminUserPermissions)
		resCount, errDelete := session.In("permission_id", removePermissionIds).In("user_id", childUserIds).Delete(aprStruct)
		if errDelete != nil {
			session.Rollback()
			return false, errDelete
		}

		if int(resCount) != len(removePermissionIds) {
			session.Rollback()
			return false, app.NewError("删除的权限数量不正确")
		}
	}

	// 刷新缓存
	for _, rId := range childUserIds {
		_, errFlush := partner_admin_permissions.DeleteCacheByUserId(rId)
		if errFlush != nil {
			session.Rollback()
			return false, errFlush
		}
	}

	// Commit Trans
	errCommit := session.Commit()
	if errCommit != nil {
		session.Rollback()
		return false, errCommit
	}

	/* =============  结束事务 =========== */

	return true, nil
}

// @title GetUserAllPermissions
// @description 获取用户所有的权限id　角色 + 个人
func (pau PartnerAdminUsers) GetUserAllPermissionIds() ([]int64, error) {
	// 1. 获取用户拥有的权限
	permissions, err := pau.GetUserAllPermissions()
	if err != nil {
		return nil, err
	}

	returnData := make([]int64, 0)
	// 角色被赋予ID
	for id, _ := range permissions {
		returnData = append(returnData, id)
	}

	return returnData, nil
}

// @title GetUserAllPermissions
// @description 获取当前用户所有的权限　角色 + 个人
func (pau PartnerAdminUsers) GetUserAllPermissions() (map[int64]*partner_admin_permissions.PartnerAdminPermissions, error) {
	// 1. 获取用户拥有的权限
	permissions, err := pau.Permissions()
	if err != nil {
		return nil, err
	}

	// 2. 获取角色
	role, errRole := pau.Role()
	if errRole != nil {
		return nil, errRole
	}

	// 3. 获取角色的权限
	rolePermissions, errPer := role.Permissions()
	if errPer != nil {
		return nil, errPer
	}

	returnData := make(map[int64]*partner_admin_permissions.PartnerAdminPermissions)

	// 用户被赋予的ID
	for idUser, itemUser := range permissions {
		returnData[idUser] = itemUser
	}

	// 角色被赋予ID
	for idRole, itemRole := range rolePermissions {
		returnData[idRole] = itemRole
	}

	return returnData, nil
}

// @title 获取管理用户　从数据库中
// @description 获取管理用户　从数据库中
func GetItemById(adminUserId int64) (*PartnerAdminUsers, error) {
	adminUser := new(PartnerAdminUsers)
	has, err := app.Db().ID(adminUserId).Get(adminUser)

	if err != nil {
		return nil, app.NewError(err)
	} else {
		if !has {
			return nil, app.NewError("对不起, 不存在的管理用户")
		}
	}

	// 管理员的角色
	_, errRole := adminUser.Role()
	if errRole != nil {
		return nil, app.NewError(errRole)
	}

	return adminUser, nil
}

// 用户是否是超级用户
func (pau PartnerAdminUsers) IsSuperAdminUser() (bool, error) {
	role, err := pau.Role()
	if err != nil {
		return false, app.NewError(err)
	}

	return role.IsSuperRole(), nil
}

// @title ChildIds
// @description 获取所有的下级ID 仅仅直接下级
func (pau PartnerAdminUsers) ChildIds() ([]int64, error) {
	allChildren, err := GetChildrenByIdFromDb(pau.Id, false)
	if err != nil {
		return nil, app.NewError(err)
	}

	childIds := make([]int64, 0)
	for id, _ := range allChildren {
		childIds = append(childIds, id)
	}

	return childIds, nil
}

// @title HaveChild
// @description 是否用户指定的下级
func (pau PartnerAdminUsers) HaveChild(childId int64) (bool, error) {
	allChildren, err := GetChildrenByIdFromDb(pau.Id, true)
	if err != nil {
		return false, app.NewError(err)
	}

	// 是否包含下级
	if _, ok := allChildren[childId]; !ok {
		return false, nil
	}

	return true, nil
}

/** =============================  关联 ============================= */

// @title Roles
// 关联 当前用户角色
func (pau PartnerAdminUsers) Role() (*partner_admin_roles.PartnerAdminRoles, error) {
	if pau.Id == 0 {
		return nil, app.NewError("对不起，用户不存在")
	}

	if pau.role != nil {
		return pau.role, nil
	}

	// 获取用户的 角色ID == 缓存
	roleId, errUserRole := partner_admin_role_users.GetRoleIdByUserId(pau.Id)

	// 如果没有查询到 直接返回
	if errUserRole != nil {
		return nil, app.NewError(errUserRole.Error())
	}

	// 获取用户的　角色对象 == 缓存
	role, err := partner_admin_roles.GetItemById(roleId)
	if err != nil {
		return nil, app.NewError(err.Error())
	}

	pau.role = role

	return pau.role, nil
}

// @title Permissions
// @description 当前 用户关联的 权限
// @return map[int64]*admin_permissions.AdminPermissions map类型
func (pau PartnerAdminUsers) Permissions() (map[int64]*partner_admin_permissions.PartnerAdminPermissions, error) {
	if pau.Id == 0 {
		return nil, app.NewError("对不起，用户不存在")
	}

	if pau.permissions != nil {
		return pau.permissions, nil
	}

	// 获取 的permissionIds 对应的对象
	isSupper, _ := pau.IsSuperAdminUser()
	permissions, err := partner_admin_permissions.GetAdminPermissionsByUserIdFromDb(pau.Id, isSupper)
	if err != nil {
		return nil, app.NewError(err.Error())
	}

	// 强制
	pau.permissions = permissions

	return pau.permissions, nil
}

/* ====================== 辅助操作 ============================ */

// @help
// 把当前角色的权限转成 map {k => v}
func (pau PartnerAdminUsers) HelpPermissionToKV() (map[int64]string, error) {
	permissions, err := pau.Permissions()
	if err != nil {
		return nil, err
	}

	returnData := make(map[int64]string)
	for k, item := range permissions {
		returnData[k] = item.Name
	}

	return returnData, nil
}

// @help
// 把当前角色的权限转成 切片 [id, id, id]
func (pau PartnerAdminUsers) HelpPermissionToKey() ([]int64, error) {
	permissions, err := pau.Permissions()
	if err != nil {
		return nil, err
	}

	returnData := make([]int64, 0)
	for k, _ := range permissions {
		returnData = append(returnData, k)
	}

	return returnData, nil
}

// @title 获取下级用户从缓存
func GetChildrenByIdFromDb(adminUserId int64, isDirectChild bool) (map[int64]*PartnerAdminUsers, error) {
	adminUser, err := GetItemFromCacheById(adminUserId)
	if err != nil {
		return nil, app.NewError(err)
	}

	// 当前用户角色
	role, errRole := adminUser.Role()
	if errRole != nil {
		return nil, app.NewError(errRole)
	}

	// 所有的下级角色id
	childRoleIds, errChild := role.GetChildRoleIds(isDirectChild)
	if errChild != nil {
		return nil, app.NewError(errChild)
	}

	// 获取帮顶的用户id
	adminUserIds, errUser := partner_admin_role_users.GetUserIdsByRoleIds(childRoleIds)
	if errUser != nil {
		return nil, app.NewError(errUser)
	}

	// 获取所有的用户对象
	adminUsers := make(map[int64]*PartnerAdminUsers)
	errFindAll := app.Db().In("id", adminUserIds).Find(&adminUsers)
	if errFindAll != nil {
		return nil, app.NewError(errFindAll)
	}

	return adminUsers, nil
}

// @title GetLang
// @description 获取用户的语言
func (pau PartnerAdminUsers) GetLang() string {
	if pau.Lang != "" {
		return pau.Lang
	}
	return app.Config.DefaultLang
}

// @title TableName
// @description join 数据类型必须返回一个主表的　表名
func (TableJoinAdminUsersAdminRoleUser) TableName() string {
	return "partner_admin_users"
}

/** ============================= Role Menus Sort ================================ */

// 角色的菜单数据结构
type RoleMenusTree struct {
	Title    string          `json:"title"`
	Route    string          `json:"route"`
	Path     string          `json:"path"`
	Icon     string          `json:"icon"`
	Sort     int             `json:"sort"`
	Children []RoleMenusTree `json:"children"`
}

type RoleMenusTreeList []RoleMenusTree

func (rl RoleMenusTreeList) Swap(i, j int) {
	rl[i], rl[j] = rl[j], rl[i]
}

func (rl RoleMenusTreeList) Less(i, j int) bool {
	return rl[i].Sort < rl[j].Sort
}

func (rl RoleMenusTreeList) Len() int {
	return len(rl)
}

// @title 获取菜单从用户的角色
// @description 用户拥有不同的角色　不同的角色有各自分配的订单 查找出来合并
func (pau PartnerAdminUsers) GetMenuFromRole() ([]RoleMenusTree, error) {

	// 获取当前用户的角色
	role, err := pau.Role()
	if err != nil {
		return nil, app.NewError("获取用户角色权限失败-" + err.Error())
	}

	// 获取所有的菜单
	menus, err := partner_admin_menus.GetItemByRoleIdFromCache(role.Id)
	if err != nil {
		return nil, app.NewError(err)
	}

	return BuildRoleMenuTree(menus, 0, pau.Lang), nil
}

// @title BuildRoleMenuTree
// @description 构建角色菜单 根据 sort 排序
func BuildRoleMenuTree(sourceData map[int64]*partner_admin_menus.PartnerAdminMenus, pid int64, lang string) []RoleMenusTree {

	buildData := make([]RoleMenusTree, 0)

	for _, item := range sourceData {
		if item.Pid == pid {
			data := RoleMenusTree{
				Path:     item.Path,
				Title:    item.TitleSign,
				Route:    item.Route,
				Sort:     item.Sort,
				Icon:     item.Icon,
				Children: BuildRoleMenuTree(sourceData, item.Id, lang),
			}
			buildData = append(buildData, data)
		}
	}

	sort.Sort(RoleMenusTreeList(buildData))
	return buildData
}

/** =============================  辅助函数 ============================= */

// 检测字段唯一性
func IsFieldExist(field string, value interface{}) bool {
	user := new(PartnerAdminUsers)
	has, err := app.Db().Where(field+" = ?", value).Get(user)

	if err != nil {
		return false
	} else {
		if !has {
			return false
		}
	}

	return true
}

var deflect int64 = 3002192

func EncodeUserId(userId int64) int64 {
	return userId*7 + deflect
}

func DecodeUserId(userId int64) (int64, error) {
	if (userId-deflect)%7 != 0 {
		return 0, fmt.Errorf("无效的token(0x002)")
	}

	return (userId - deflect) / 7, nil
}
